package com.zhuanzhuan.hero.user.facade;

import cn.hutool.core.util.RandomUtil;
import com.bj58.spat.scf.server.contract.annotation.ServiceBehavior;
import com.bj58.youpin.common.rpc.result.Result;
import com.zhuanzhuan.hero.member.response.MemberDTO;
import com.zhuanzhuan.hero.user.consts.Consts;
import com.zhuanzhuan.hero.user.consts.NumConsts;
import com.zhuanzhuan.hero.user.converter.UserInfoConvert;
import com.zhuanzhuan.hero.user.dto.tool.FlushUserDTO;
import com.zhuanzhuan.hero.user.dto.tool.ToolCreateLabelDTO;
import com.zhuanzhuan.hero.user.entity.HeroLabelInfo;
import com.zhuanzhuan.hero.user.entity.HeroUserContact;
import com.zhuanzhuan.hero.user.entity.HeroUserInfo;
import com.zhuanzhuan.hero.user.enums.*;
import com.zhuanzhuan.hero.user.exception.BusinessException;
import com.zhuanzhuan.hero.user.helper.HeroMemberHelper;
import com.zhuanzhuan.hero.user.helper.ZzUserHelper;
import com.zhuanzhuan.hero.user.mapper.HeroLabelInfoMapper;
import com.zhuanzhuan.hero.user.pojo.bo.QueryUserInfoParam;
import com.zhuanzhuan.hero.user.pojo.po.UserPO;
import com.zhuanzhuan.hero.user.service.HeroUserContactService;
import com.zhuanzhuan.hero.user.service.HeroUserInfoService;
import com.zhuanzhuan.hero.user.util.Assert;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @ClassName SmallToolFacadeImpl
 * @Description
 * @Author hanjunjun
 * @Date 2024/6/25 11:26
 */
@ServiceBehavior
@Slf4j
public class SmallToolFacadeImpl implements ISmallToolFacade {

    @Resource
    private HeroLabelInfoMapper labelInfoMapper;

    @Resource
    private HeroMemberHelper heroMemberHelper;

    @Resource
    private HeroUserInfoService heroUserInfoService;

    @Resource
    private HeroUserContactService heroUserContactService;

    private final Integer ENCRYPT_MOBILE_LEN = 40;

    @Override
    public Result<Void> createManagementLabel(@Valid ToolCreateLabelDTO dto) {
        HeroLabelInfo labelInfo = new HeroLabelInfo();
        Integer labelType = dto.getLabelType();
        Assert.notNull(labelType, ExceptionMsgEnum.PARAM_ERROR);
        labelInfo.setLabelType(labelType);
        String labelCode = dto.getLabelCode();
        if (Arrays.asList(LabelTypeEnum.MANAGEMENT.getCode(), LabelTypeEnum.ADVANTAGE.getCode()).contains(labelType)
            && StringUtils.isBlank(labelCode)) {
            labelCode = this.generateLabelCode(labelType);
        }
        labelInfo.setLabelCode(labelCode);
        labelInfo.setLabelName(dto.getLabelName());
        labelInfo.setParentLabelCode(dto.getParentLabelCode());
        labelInfo.setLabelLevel(dto.getLabelLevel());
        labelInfo.setShowOrder(dto.getShowOrder());
        Integer createRole = dto.getCreateRole();
        if (Objects.isNull(createRole)) {
            createRole = CreaterRoleEnum.SYSTEM.getCode();
        }
        labelInfo.setCreaterRole(createRole);
        labelInfo.setState(StateEnum.EFFECTIVE.getCode());
        labelInfo.setCreateBy(NumConsts.SYSTEM_CODE);
        labelInfo.setUpdateBy(NumConsts.SYSTEM_CODE);

        labelInfoMapper.insertSelective(labelInfo);
        return Result.success();
    }

    @Override
    public Result<Boolean> createBackBusinessLabel(ToolCreateLabelDTO dto) {
        String labelName = dto.getLabelName();
        if (StringUtils.isBlank(labelName)) {
            throw new BusinessException(ExceptionMsgEnum.PARAM_ERROR);
        }
        HeroLabelInfo labelInfo = new HeroLabelInfo();
        labelInfo.setLabelType(LabelTypeEnum.FRATERNITY_AUTH.getCode());
        labelInfo.setLabelName(labelName);
        labelInfo.setParentLabelCode(Consts.FIRST_LEVEL_PARENT_DEFAULT_CODE);
        labelInfo.setLabelLevel(NumConsts.ONE);
        labelInfo.setShowOrder(NumConsts.ONE);
        labelInfo.setCreaterRole(CreaterRoleEnum.BUSINESS.getCode());
        labelInfo.setState(StateEnum.EFFECTIVE.getCode());
        labelInfo.setCreateBy(NumConsts.SYSTEM_CODE);
        labelInfo.setUpdateBy(NumConsts.SYSTEM_CODE);

        labelInfoMapper.insertSelective(labelInfo);
        return Result.success();
    }

    @Override
    public Result<Void> flushUserMemberLevel(@Valid FlushUserDTO dto) {
        List<Long> uids = dto.getUids();
        QueryUserInfoParam queryUserInfoParam = new QueryUserInfoParam();
        queryUserInfoParam.setUids(uids);
        List<UserPO> userInfos = heroUserInfoService.listByParam(queryUserInfoParam);
        uids = userInfos
            .stream()
            .map(UserPO::getUid)
            .distinct()
            .collect(Collectors.toList());

        //TODO 分批去查
        List<MemberDTO> memberList = heroMemberHelper.listMember(uids);
        if (CollectionUtils.isEmpty(memberList)) {
            return Result.success(null);
        }
        Map<Long, MemberDTO> uidMemberMap =
            memberList.stream().collect(Collectors.toMap(MemberDTO::getUid, Function.identity()));

        List<HeroUserInfo> updateUserList = new ArrayList<>();
        userInfos.forEach(userInfo -> {
            MemberDTO memberDTO = uidMemberMap.get(userInfo.getUid());
            HeroUserInfo updateUser = new HeroUserInfo();
            updateUser.setId(userInfo.getId());
            updateUser.setUpdateBy(NumConsts.SYSTEM_CODE);
            if (Objects.nonNull(memberDTO)) {
                updateUser.setMemberLevel(memberDTO.getMemberLevel());
                updateUser.setUserState(UserInfoConvert.mapUserStateByMemberStatus(memberDTO.getMemberStatus()).getCode());
                updateUser.setSettleTime(Objects.isNull(memberDTO.getFirstActivateTime()) ?
                    userInfo.getCreateTime() : memberDTO.getFirstActivateTime());
            } else {
                log.info("没有会员信息 uid={}", userInfo.getUid());
                //没有会员信息  更新成待入驻
                updateUser.setMemberLevel(null);
                updateUser.setUserState(UserStateEnum.WAIT_SETTLE.getCode());
                updateUser.setSettleTime(null);
            }
            updateUserList.add(updateUser);
        });

        if (CollectionUtils.isNotEmpty(updateUserList)) {
            log.info("更新人数：{}", updateUserList.size());
            heroUserInfoService.updateBatchById(updateUserList);
        }

        return Result.success(null);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<Boolean> flushUserEncrypt(FlushUserDTO dto, boolean isEncrypt) {
        List<Long> uids = dto.getUids();
        List<Long> excludeUids = dto.getExcludeUids();

        QueryUserInfoParam queryUserInfoParam = new QueryUserInfoParam();
        queryUserInfoParam.setUids(uids);
        List<UserPO> userInfos = heroUserInfoService.listByParam(queryUserInfoParam);
        if (CollectionUtils.isEmpty(userInfos)) {
            log.info("查询用户信息为空");
            return Result.success(true);
        }

        List<HeroUserInfo> userUpdateList = new ArrayList<>();
        userInfos.forEach(userInfo -> {
            if (!excludeUids.contains(userInfo.getUid())) {
                HeroUserInfo update = new HeroUserInfo();
                update.setId(userInfo.getId());
                update.setMobile(isEncrypt ? ZzUserHelper.encrypt(userInfo.getMobile()) :
                    ZzUserHelper.decrypt(userInfo.getMobile()));
                userUpdateList.add(update);
            }
        });
        if (CollectionUtils.isNotEmpty(userUpdateList)) {
            heroUserInfoService.updateBatchById(userUpdateList, 1000);
        }

        uids = userInfos.stream().map(UserPO::getUid).distinct().collect(Collectors.toList());

        List<HeroUserContact> userContacts = heroUserContactService.listByUid(uids);
        List<HeroUserContact> userContactUpdateList = new ArrayList<>();
        userContacts.forEach(userContact -> {
            if (!excludeUids.contains(userContact.getUid())) {
                HeroUserContact update = new HeroUserContact();
                update.setId(userContact.getId());
                if (isEncrypt) {
                    update.setContactMobile(ZzUserHelper.encrypt(userContact.getContactMobile()));
                    update.setStoreAddress(ZzUserHelper.encrypt(userContact.getStoreAddress()));
                } else {
                    update.setContactMobile(ZzUserHelper.decrypt(userContact.getContactMobile()));
                    update.setStoreAddress(ZzUserHelper.decrypt(userContact.getStoreAddress()));
                }
                userContactUpdateList.add(update);
            }
        });
        if (CollectionUtils.isNotEmpty(userContactUpdateList)) {
            heroUserContactService.updateBatchById(userContactUpdateList, 1000);
        }

        return Result.success(true);
    }

    @Override
    public Result<Boolean> flushUserDecrypt(FlushUserDTO dto) {
        List<Long> uids = dto.getUids();

        QueryUserInfoParam queryUserInfoParam = new QueryUserInfoParam();
        queryUserInfoParam.setUids(uids);
        List<UserPO> userInfos = heroUserInfoService.listByParam(queryUserInfoParam);

        List<HeroUserInfo> userUpdateList = new ArrayList<>();
        userInfos.forEach(userInfo -> {
            String mobile = userInfo.getMobile();
            if (mobile.length() > ENCRYPT_MOBILE_LEN) {
                HeroUserInfo update = new HeroUserInfo();
                update.setId(userInfo.getId());
                String decrypt = ZzUserHelper.decrypt(mobile);
                update.setMobile(decrypt);
                userUpdateList.add(update);
            }
        });
        if (CollectionUtils.isNotEmpty(userUpdateList)) {
            heroUserInfoService.updateBatchById(userUpdateList, 1000);
        }

        uids = userInfos.stream().map(UserPO::getUid).distinct().collect(Collectors.toList());

        List<HeroUserContact> userContacts = heroUserContactService.listByUid(uids);
        List<HeroUserContact> userContactUpdateList = new ArrayList<>();
        userContacts.forEach(userContact -> {
            String contactMobile = userContact.getContactMobile();
            if (contactMobile.length() > ENCRYPT_MOBILE_LEN) {
                HeroUserContact update = new HeroUserContact();
                update.setId(userContact.getId());
                update.setContactMobile(ZzUserHelper.decrypt(contactMobile));
                update.setStoreAddress(ZzUserHelper.decrypt(userContact.getStoreAddress()));
                userContactUpdateList.add(update);
            }
        });
        if (CollectionUtils.isNotEmpty(userContactUpdateList)) {
            heroUserContactService.updateBatchById(userContactUpdateList, 1000);
        }

        return Result.success(true);
    }

    /**
     * 生成经营标签、优势介绍的labelCode
     *
     * @param labelType
     * @return java.lang.String
     * @author  hanjunjun
     * @date 2024/8/8
     **/
    public String generateLabelCode(Integer labelType) {
        return labelType + Consts.LABEL_CODE_SPLIT + RandomUtil.randomStringUpper(4);
    }

    public static void main(String []args){
        System.out.println(new SmallToolFacadeImpl().generateLabelCode(2));
    }
}
